

/* 增加fpu上下文 */

#define RESUME_FPU


#include <libcoco.h>
#include <dbg.h>
#include <dcont/pcorou.h>
#include <dcont/ptrampl.h>
#include <dinfra/hstack.h>
#include <stdlib.h>

#include <page_alloc.h>

/* corou buf */

/* 实现类似gstack的玩意 */

/* 用于快速实现ressume, 消除一个resume分支, 注意不能使用浮点上下文! */
// #define FAST_RESUME

#ifdef FAST_RESUME
	#define WRAPPER_FUNC		__corou_trampoline_yield
	#define CREATE_WRAPPER_FUNC __corou_trampoline_yield
#else
	#define WRAPPER_FUNC		__corou_trampoline
	#define CREATE_WRAPPER_FUNC NULL_PTR
#endif


#define STACK_HEAP_INCR_ONCE_SIZE	   (SIZE_1G)
/* TODO: 大于2M应该拒绝分配 */
#define STACK_HEAP_SLAB_SIZE			(SIZE_64K)


static TLS_INITIAL hstack_ctrl_t tctrl;
DEF_HSTACK(crout, 0, STACK_HEAP_INCR_ONCE_SIZE, STACK_HEAP_SLAB_SIZE, &tctrl, page_alloc, page_free, mark_unused_pages)
DEF_HSTACK_SHARE(crout_share, 0, STACK_HEAP_INCR_ONCE_SIZE, STACK_HEAP_SLAB_SIZE, &tctrl, page_alloc, page_free, mark_unused_pages)

SAI void  builtin_int_free(void *ptr, size_t size){
	PARAM_USED(size);
	// fprintf(stderr, "ret %p\n", ptr);
	return __builtin_free(ptr);
}
SAI void*  builtin_int_malloc(size_t size, size_t *real_size){
	size = align_up(size + sizeof(corou_t), HDEF_STK_ALIGN_BYTES);
	void *ptr = __builtin_malloc(size);
	*real_size = size;
	// fprintf(stderr, "get %p\n", ptr);
	return ptr;
}

DEF_COROU_ALLOC(heaptls, crout_hstack_get, crout_hstack_ret, CREATE_WRAPPER_FUNC)
DEF_COROU_ALLOC(heaptls_share, crout_share_hstack_get, crout_share_hstack_ret, CREATE_WRAPPER_FUNC)

DEF_COROU_ALLOC(dft, builtin_int_malloc, builtin_int_free, CREATE_WRAPPER_FUNC)

// #define COROU_CREATE	heaptls_corou_create 
// #define COROU_FREE	  heaptls_corou_release
#ifdef MALLOC_COROU_CREATE
	#define COROU_CREATE	dft_corou_create
	#define COROU_FREE	  dft_corou_release
#else
	#define COROU_CREATE	heaptls_share_corou_create 
	#define COROU_FREE	  heaptls_share_corou_release
#endif

static TLS_INITIAL prompt_t *cur_prompt;
static TLS_INITIAL presume_t root_prompt;
DEF_PROMPT_MODULE(cur_prompt, (prompt_t *)&root_prompt)

/* 注意这玩意 */
int 	crout_create( crout_t **pco,const crout_attr_t *attr,void *(*routine)(void*),void *arg){
	corou_t *c = COROU_CREATE(attr->stack_size, (void *)routine, (word_t)arg);
	if (UNLIKELY((!c) || (!pco))) return -1;
	*pco = (crout_t *)c;

	// 使用c->func做标记
	// c->prm.func_ptr = (void *)((word_t)(c->prm.func_ptr) | 0x1UL);
	c->prm.cofun_ptr = (ipromptf_t *)((paddr_t)c->prm.cofun_ptr | 0x1UL);
	return 0;
}

void	crout_resume( crout_t *co){
	corou_t *c = (corou_t *)co;
#ifdef FAST_RESUME
	corou_resume(c, c->arg);
#else
	// if (UNLIKELY(0 == c->stk_size & 0x1)){
		// c->stk_size |= 0x1;
	if (UNLIKELY(0 != ((word_t)c->prm.func_ptr & 0x1))){
		// c->prm.func_ptr = (void *)((word_t)(c->prm.func_ptr) & (~0x1));
		c->prm.cofun_ptr = (ipromptf_t *)((paddr_t)c->prm.cofun_ptr & (~0x1));
		prompt_exec(&c->prm, WRAPPER_FUNC, (word_t)c);
	}
	else{
		/* 从crout中恢复sse/fpu上下文 */
		prompt_resume(&c->prm);
	}
#endif
}

void	crout_yield( crout_t *co ){
	corou_t *c = (corou_t *)co;
	
	prompt_yield(&c->prm);
}

void	crout_release( crout_t *co ){
	corou_t *c = (corou_t *)co;
#ifndef FAST_RESUME
	// c->stk_size &= ~0x1;
#endif

#ifdef __BUILTIN_COROU_CREATE
	PREFETCH(c->mblk_ptr);
#endif
	COROU_FREE(c);
}

void	crout_reset(crout_t * co){
	corou_t *c = (corou_t *)co;
	// PREFETCH(c->mblk_ptr);
	#ifdef FAST_RESUME
	prompt_exec(&(c->prm), WRAPPER_FUNC, (word_t)c);
	#else
	//c->stk_size &= ~0x1;
	// c->prm.func_ptr = (void *)((word_t)(c->prm.func_ptr) | 0x1UL);
	c->prm.cofun_ptr = (ipromptf_t *)((paddr_t)c->prm.cofun_ptr | 0x1UL);
	#endif
}
